﻿'-------------------------------------------------------------------------------
'Developer: Ivan Tamurejo
'-------------------------------------------------------------------------------
'This class allows compilations by an order of compilation list and also enables
'a compilation of a single component.
'
'Required classes 'Component' and 'VB6Project'.
'-------------------------------------------------------------------------------

Imports System.IO
Imports System.Reflection.Assembly

Public Class VB6Builds

#Region "Private variables"

    Private lComponents As List(Of String)
    Private lCLSID As List(Of String)

    Private Requirements() As String
    Private CompilationOrder() As String
    Private ReferencesOrder() As String

    Private oVB6Project As VB6Project
    Private oComponent As Component
    Private IsDisposed As Boolean

    Private _BuildsDirectory As String
    Private _CompilerFilePath As String
    Private _VBPOutDirectory As String

    Private _VersionLegalTradeMarks As String
    Private _MajorVer As String
    Private _MinorVer As String
    Private _RevisionVer As String

    Private _LastWriteDate As String
    Private _LastWriteTime As String

    Private _ContinueOnError As Boolean
    Private _ModifyProjectProperties As Boolean

    Private _MessageDescription As String
    Private _MessageContentWithErrors As String
    Private _MessageContentWithoutErrors As String

#End Region

#Region "Procedures -New- and -Finalize-"

    Public Sub New()

        Try

            BuildsDirectory = IniGet(PathINI, "BUILDS", "BuildsDirectory")
            CompilerFilePath = IniGet(PathINI, "BUILDS", "CompilerFilePath")
            VBPOutDirectory = IniGet(PathINI, "BUILDS", "VBPOutDirectory")
            VersionLegalTradeMarks = IniGet(PathINI, "BUILDS", "VersionLegalTradeMarks")
            MajorVer = IniGet(PathINI, "BUILDS", "MajorVer")
            MinorVer = IniGet(PathINI, "BUILDS", "MinorVer")
            RevisionVer = IniGet(PathINI, "BUILDS", "RevisionVer")
            LastWriteDate = IniGet(PathINI, "BUILDS", "LastWriteDate")
            LastWriteTime = IniGet(PathINI, "BUILDS", "LastWriteTime")
            ContinueOnError = (IniGet(PathINI, "BUILDS", "ContinueOnError") = "1")
            ModifyProjectProperties = (IniGet(PathINI, "BUILDS", "ModifyProjectProperties") = "1")
            MessageDescription = IniGet(PathINI, "NOTIFY", "MessageDescription")
            MessageContentWithErrors = IniGet(PathINI, "NOTIFY", "MessageContentWithErrors")
            MessageContentWithoutErrors = IniGet(PathINI, "NOTIFY", "MessageContentWithoutErrors")

        Catch ex As Exception

            Throw New Exception(ex.Message)

        End Try

    End Sub

    Public Sub Dispose()

        Finalize()

    End Sub

    Protected Overrides Sub Finalize()
        MyBase.Finalize()

        If Not IsDisposed Then

            lComponents = Nothing
            lCLSID = Nothing
            Requirements = Nothing
            CompilationOrder = Nothing
            ReferencesOrder = Nothing
            oVB6Project = Nothing
            oComponent = Nothing

            IsDisposed = True

        End If

    End Sub

#End Region

#Region "Properties to indicate the builds directory and the path file to the compiler"

    Public Property BuildsDirectory() As String
        Get
            If Not Directory.Exists(_BuildsDirectory) Then

                Throw New Exception("> Builds directory does not valid or not exist.")

            End If

            Return _BuildsDirectory
        End Get
        Set(ByVal value As String)
            _BuildsDirectory = value

            If Not Directory.Exists(_BuildsDirectory) Then

                Throw New Exception("> Builds directory does not valid or not exist.")

            End If

        End Set
    End Property

    Public Property CompilerFilePath() As String
        Get
            If _CompilerFilePath = "" Then
                _CompilerFilePath = "C:\Archivos de programa\Microsoft Visual Studio\VB98\VB6.EXE"
            End If

            If Not File.Exists(_CompilerFilePath) Then

                Throw New Exception("> Compiler file does not valid or not exist.")

            End If

            Return _CompilerFilePath
        End Get
        Set(ByVal value As String)
            _CompilerFilePath = value

            If Not File.Exists(_CompilerFilePath) Then

                Throw New Exception("> Compiler file does not valid or not exist.")

            End If

        End Set
    End Property

    Public Property VBPOutDirectory() As String
        Get
            If _VBPOutDirectory <> "" And Not Directory.Exists(_VBPOutDirectory) Then

                Throw New Exception("> VBP Out directory does not valid or not exist.")

            End If

            Return _VBPOutDirectory
        End Get
        Set(ByVal value As String)
            _VBPOutDirectory = value

            If _VBPOutDirectory <> "" And Not Directory.Exists(_VBPOutDirectory) Then

                Throw New Exception("> VBP Out directory does not valid or not exist.")

            End If

        End Set
    End Property

    Public Property VersionLegalTradeMarks() As String
        Get
            Return _VersionLegalTradeMarks
        End Get
        Set(ByVal value As String)
            _VersionLegalTradeMarks = value
        End Set
    End Property

    Public Property MajorVer() As String
        Get
            Return _MajorVer
        End Get
        Set(ByVal value As String)
            _MajorVer = value
        End Set
    End Property

    Public Property MinorVer() As String
        Get
            Return _MinorVer
        End Get
        Set(ByVal value As String)
            _MinorVer = value
        End Set
    End Property

    Public Property RevisionVer() As String
        Get
            Return _RevisionVer
        End Get
        Set(ByVal value As String)
            _RevisionVer = value
        End Set
    End Property

    Public Property LastWriteDate() As String
        Get
            If _LastWriteDate = "" Then
                _LastWriteDate = Left(Date.Today.ToString, 10)
            End If

            Return _LastWriteDate
        End Get
        Set(ByVal value As String)
            _LastWriteDate = value
        End Set
    End Property

    Public Property LastWriteTime() As String
        Get
            If _LastWriteTime = "" Then
                _LastWriteTime = TimeString
            End If

            Return _LastWriteTime
        End Get
        Set(ByVal value As String)
            _LastWriteTime = value
        End Set
    End Property

    Public Property ContinueOnError() As Boolean
        Get
            Return _ContinueOnError
        End Get
        Set(ByVal value As Boolean)
            _ContinueOnError = value
        End Set
    End Property

    Public Property ModifyProjectProperties() As Boolean
        Get
            Return _ModifyProjectProperties
        End Get
        Set(ByVal value As Boolean)
            _ModifyProjectProperties = value
        End Set
    End Property

    Public Property MessageDescription() As String
        Get
            Return _MessageDescription
        End Get
        Set(ByVal value As String)
            _MessageDescription = value
        End Set
    End Property

    Public Property MessageContentWithErrors() As String
        Get
            Return _MessageContentWithErrors
        End Get
        Set(ByVal value As String)
            _MessageContentWithErrors = value
        End Set
    End Property

    Public Property MessageContentWithoutErrors() As String
        Get
            Return _MessageContentWithoutErrors
        End Get
        Set(ByVal value As String)
            _MessageContentWithoutErrors = value
        End Set
    End Property

#End Region

#Region "Public procedures of the robot"

    Public Sub StartBuilds(ByVal ProjectFileOrCompilationOrderFile As String, _
                           ByVal OutDir As String, _
                           ByVal WriteTime As Boolean)

        'We get the path of the project file
        Dim ProjectFilePath As String = GetProjectFilePath(ProjectFileOrCompilationOrderFile)
        Dim ProjectProperties() As String = Nothing

        If Not File.Exists(ProjectFilePath) Then

            If UCase(Path.GetExtension(ProjectFilePath)) = ".VBP" Then

                Throw New Exception("> The project file '" & ProjectFilePath & "' is not found.")

            Else
                Throw New Exception("> The compilation order file '" & ProjectFilePath & "' is not found.")

            End If

        Else

            If UCase(Path.GetExtension(ProjectFilePath)) = ".VBP" Then

                If Not ModifyProjectProperties Then
                    '-------------------------------------------------------------------------------------
                    'If you have entered in the configuration that we want to make compilations 
                    'respecting the project settings.
                    '-------------------------------------------------------------------------------------

                    'Load the project
                    '-------------------------------------------------------------------------------------
                    oVB6Project = New VB6Project(ProjectFilePath)
                    If Not oVB6Project Is Nothing Then

                        If oVB6Project.Load() Then

                            'If the project has not been compiled previously we do the compilation,
                            'in the case that we got out without doing anything.
                            If Not File.Exists(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild)) Then

                                oVB6Project.CompilerFilePath = CompilerFilePath
                                oVB6Project.BuildsDirectory = BuildsDirectory
                                If oVB6Project.Build() Then

                                    If OutDir <> "" Then
                                        CopyFileTo(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild), OutDir)

                                        If WriteTime Then
                                            SetWriteLastTimeFile(Path.Combine(OutDir, oVB6Project.NameFileBuild))
                                        End If
                                    End If

                                Else

                                    oVB6Project.Dispose()
                                    Throw New Exception("> Error in compilation of the component '" & ProjectFilePath & "'")

                                End If

                            Else

                                oVB6Project.Dispose()
                                WriteLog(BuildsDirectory, "> The component has already been compiled previously.", eTypeLog.Robot)

                            End If

                        End If

                    End If
                    '-------------------------------------------------------------------------------------

                Else
                    '-------------------------------------------------------------------------------------
                    'If the configuration has indicated that we want to perform compilation 
                    'by modifying the properties of the project to compile breaking compatibility.
                    '-------------------------------------------------------------------------------------

                    'We get the path of the files that are required before the compilation.
                    If File.Exists(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "Requirements.txt")) Then
                        Requirements = GetAllLinesFileEncondingDefault(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "Requirements.txt"))
                    End If
                    If File.Exists(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "ReferencesOrder.txt")) Then
                        ReferencesOrder = GetAllLinesFileEncondingDefault(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "ReferencesOrder.txt"))
                    End If

                    lComponents = New List(Of String)
                    lCLSID = New List(Of String)

                    'We get the components and their CLSID of the required before compilation files.
                    '-------------------------------------------------------------------------------------
                    If Not Requirements Is Nothing Then
                        For Each sRequirement As String In Requirements

                            If Not File.Exists(sRequirement) Then

                                Throw New Exception("> The requirement '" & sRequirement & "' is not found.")

                            Else
                                oComponent = New Component(sRequirement)
                                If Not oComponent Is Nothing Then
                                    If oComponent.GetCLSID <> "" Then
                                        lComponents.Add(UCase(Path.GetFileName(sRequirement)))
                                        lCLSID.Add(oComponent.GetCLSID)
                                        oComponent.Dispose()
                                    End If
                                End If
                            End If

                        Next
                    End If
                    '-------------------------------------------------------------------------------------

                    'We get the components and their CLSID have already been compiled in the builds 
                    'directory.
                    '-------------------------------------------------------------------------------------
                    For Each sComponent In Directory.GetFiles(BuildsDirectory)

                        oComponent = New Component(sComponent)
                        If Not oComponent Is Nothing Then

                            If oComponent.GetCLSID <> "" Then
                                lComponents.Add(UCase(Path.GetFileName(sComponent)))
                                lCLSID.Add(oComponent.GetCLSID & "#" & oComponent.GetMajorVersion & "." & oComponent.GetMinorVersion)
                            End If

                            oComponent.Dispose()
                        End If

                    Next
                    '-------------------------------------------------------------------------------------


                    'We do the compilation of the specified component.
                    '-------------------------------------------------------------------------------------
                    'We get the properties that must be modified in the project being file compiling.
                    ProjectProperties = GetProjectProperties(ProjectFileOrCompilationOrderFile)
                    oVB6Project = New VB6Project(ProjectFilePath)
                    If Not oVB6Project Is Nothing Then

                        If oVB6Project.Load() Then

                            'Set properties specific
                            For Each sProperty As String In ProjectProperties
                                oVB6Project.SetProjectProperty(Trim(Mid(sProperty, 1, InStr(sProperty, "=") - 1)), Trim(Mid(sProperty, InStr(sProperty, "=") + 1)), False)
                            Next

                            If Not File.Exists(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild)) Then

                                'If the component being compiled is an OCX file then we must maintain the compatibility
                                'of project. For any other component we break the compatibility to generate a new CLSID.
                                If UCase(Path.GetExtension(oVB6Project.NameFileBuild)) = ".OCX" Then
                                    oVB6Project.SetProjectProperty("CompatibleMode", Chr(34) & "1" & Chr(34), False)
                                Else
                                    oVB6Project.SetProjectProperty("CompatibleMode", Chr(34) & "0" & Chr(34), False)
                                End If

                                'Set general properties 
                                If VersionLegalTradeMarks <> "" Then oVB6Project.SetProjectProperty("VersionLegalTradeMarks", Chr(34) & VersionLegalTradeMarks & Chr(34), False)
                                If MajorVer <> "" Then oVB6Project.SetProjectProperty("MajorVer", MajorVer, False)
                                If MinorVer <> "" Then oVB6Project.SetProjectProperty("MinorVer", MinorVer, False)
                                If RevisionVer <> "" Then oVB6Project.SetProjectProperty("RevisionVer", RevisionVer, False)

                                'Sort References, replace CLSID's and Save
                                oVB6Project.SortReferences(ReferencesOrder)
                                oVB6Project.ReplaceCLSID(lComponents, lCLSID)
                                oVB6Project.Save()

                                'Build and save the new CLSID
                                oVB6Project.CompilerFilePath = CompilerFilePath
                                oVB6Project.BuildsDirectory = BuildsDirectory
                                If oVB6Project.Build() Then

                                    If oVB6Project.CLSID <> "" Then
                                        lComponents.Add(UCase(oVB6Project.NameFileBuild))
                                        lCLSID.Add(oVB6Project.CLSID & "#" & oVB6Project.MajorVersion & "." & oVB6Project.MinorVersion)
                                    End If

                                    If UCase(Path.GetExtension(oVB6Project.NameFileBuild)) = ".EXE" Then
                                        'For exe's files set compilation without compatibility and Save.
                                        oVB6Project.SetProjectProperty("CompatibleMode", Chr(34) & "0" & Chr(34), False)
                                    Else
                                        'Set compilation with compatibility and Save.
                                        oVB6Project.SetProjectProperty("CompatibleMode", Chr(34) & "2" & Chr(34), False)
                                    End If

                                    If VBPOutDirectory = "" Then
                                        oVB6Project.Save()
                                    Else
                                        oVB6Project.SaveAs(VBPOutDirectory)
                                        'If a new project file has been generated we must make the original project unchanged file.
                                        oVB6Project.SaveOriginal()
                                    End If

                                    If OutDir <> "" Then
                                        CopyFileTo(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild), OutDir)

                                        If WriteTime Then
                                            SetWriteLastTimeFile(Path.Combine(OutDir, oVB6Project.NameFileBuild))
                                        End If
                                    End If

                                Else

                                    If VBPOutDirectory = "" Then
                                        oVB6Project.Save()
                                    Else
                                        oVB6Project.SaveAs(VBPOutDirectory)
                                        'If a new project file has been generated we must make the original project unchanged file.
                                        oVB6Project.SaveOriginal()
                                    End If

                                    oVB6Project.Dispose()
                                    Throw New Exception("> Error in compilation of the component '" & ProjectFilePath & "'")

                                End If

                            Else

                                oVB6Project.Dispose()
                                WriteLog(BuildsDirectory, "> The component has already been compiled previously.", eTypeLog.Robot)

                            End If

                        End If

                        oVB6Project.Dispose()

                    End If
                    '-------------------------------------------------------------------------------------

                End If

                'Clean .oca files
                CleanOCAFiles()

            Else

                StartBuildsList(ProjectFileOrCompilationOrderFile, OutDir, WriteTime)

            End If

        End If

    End Sub

    Private Sub StartBuildsList(ByVal CompilationOrderFile As String, _
                                ByVal OutDir As String, _
                                ByVal WriteTime As Boolean)

        Dim ProjectFilePath As String = ""
        Dim ProjectProperties() As String = Nothing

        'We get the order of compilation. It is necessary for batch compilation.
        CompilationOrder = GetAllLinesFileEncondingDefault(CompilationOrderFile)

        If Not ModifyProjectProperties Then
            '-------------------------------------------------------------------------------------
            'If you have entered in the configuration that we want to make compilations 
            'respecting the project settings.
            '-------------------------------------------------------------------------------------

            'We do the compilation batch according to the order of compilation.
            '-------------------------------------------------------------------------------------
            For Each ProjectFileLine As String In CompilationOrder

                'We get the path of the project file
                ProjectFilePath = GetProjectFilePath(ProjectFileLine)
                If Not File.Exists(ProjectFilePath) Then

                    'The component does not exist
                    Throw New Exception("> The project file '" & ProjectFilePath & "' is not found.")

                Else

                    'We get the properties that must be modified in the project being file compiling.
                    oVB6Project = New VB6Project(ProjectFilePath)
                    If Not oVB6Project Is Nothing Then

                        If oVB6Project.Load() Then

                            If Not File.Exists(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild)) Then

                                oVB6Project.CompilerFilePath = CompilerFilePath
                                oVB6Project.BuildsDirectory = BuildsDirectory
                                If oVB6Project.Build() Then

                                    If OutDir <> "" Then
                                        CopyFileTo(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild), OutDir)

                                        If WriteTime Then
                                            SetWriteLastTimeFile(Path.Combine(OutDir, oVB6Project.NameFileBuild))
                                        End If
                                    End If

                                Else

                                    If Not ContinueOnError Then

                                        'Destroy object and exit
                                        oVB6Project.Dispose()
                                        Throw New Exception("> Error in compilation of the component '" & ProjectFilePath & "'")

                                    End If

                                End If

                            End If

                        End If

                        oVB6Project.Dispose()

                    End If

                End If

            Next
            '-------------------------------------------------------------------------------------

        Else
            '-------------------------------------------------------------------------------------
            'If the configuration has indicated that we want to perform compilation 
            'by modifying the properties of the project to compile breaking compatibility.
            '-------------------------------------------------------------------------------------

            'We get the path of the files that are required before the compilation.
            If File.Exists(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "Requirements.txt")) Then
                Requirements = GetAllLinesFileEncondingDefault(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "Requirements.txt"))
            End If
            If File.Exists(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "ReferencesOrder.txt")) Then
                ReferencesOrder = GetAllLinesFileEncondingDefault(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "ReferencesOrder.txt"))
            End If

            lComponents = New List(Of String)
            lCLSID = New List(Of String)

            'We get the components and their CLSID of the required before compilation files.
            '-------------------------------------------------------------------------------------
            If Not Requirements Is Nothing Then
                For Each sRequirement As String In Requirements

                    If Not File.Exists(sRequirement) Then

                        Throw New Exception("> The requirement '" & sRequirement & "' is not found.")

                    Else
                        oComponent = New Component(sRequirement)
                        If Not oComponent Is Nothing Then
                            If oComponent.GetCLSID <> "" Then
                                lComponents.Add(UCase(Path.GetFileName(sRequirement)))
                                lCLSID.Add(oComponent.GetCLSID)
                                oComponent.Dispose()
                            End If
                        End If
                    End If

                Next
            End If
            '-------------------------------------------------------------------------------------

            'We do the compilation batch according to the order of compilation.
            '-------------------------------------------------------------------------------------
            For Each ProjectFileLine As String In CompilationOrder

                'We get the path of the project file
                ProjectFilePath = GetProjectFilePath(ProjectFileLine)
                If Not File.Exists(ProjectFilePath) Then

                    'The component does not exist
                    Throw New Exception("> The project file '" & ProjectFilePath & "' is not found.")

                Else

                    'We get the properties that must be modified in the project being file compiling.
                    ProjectProperties = GetProjectProperties(ProjectFileLine)
                    oVB6Project = New VB6Project(ProjectFilePath)
                    If Not oVB6Project Is Nothing Then

                        If oVB6Project.Load() Then

                            'Set properties specific
                            For Each sProperty As String In ProjectProperties
                                oVB6Project.SetProjectProperty(Trim(Mid(sProperty, 1, InStr(sProperty, "=") - 1)), Trim(Mid(sProperty, InStr(sProperty, "=") + 1)), False)
                            Next

                            If Not File.Exists(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild)) Then

                                'If the component being compiled is an OCX file then we must maintain the compatibility
                                'of project. For any other component we break the compatibility to generate a new CLSID.
                                If UCase(Path.GetExtension(oVB6Project.NameFileBuild)) = ".OCX" Then
                                    oVB6Project.SetProjectProperty("CompatibleMode", Chr(34) & "1" & Chr(34), False)
                                Else
                                    oVB6Project.SetProjectProperty("CompatibleMode", Chr(34) & "0" & Chr(34), False)
                                End If

                                'Set properties general
                                If VersionLegalTradeMarks <> "" Then oVB6Project.SetProjectProperty("VersionLegalTradeMarks", Chr(34) & VersionLegalTradeMarks & Chr(34), False)
                                If MajorVer <> "" Then oVB6Project.SetProjectProperty("MajorVer", MajorVer, False)
                                If MinorVer <> "" Then oVB6Project.SetProjectProperty("MinorVer", MinorVer, False)
                                If RevisionVer <> "" Then oVB6Project.SetProjectProperty("RevisionVer", RevisionVer, False)

                                'Sort references, replace CLSID's and Save
                                oVB6Project.SortReferences(ReferencesOrder)
                                oVB6Project.ReplaceCLSID(lComponents, lCLSID)
                                oVB6Project.Save()

                                'Build and save the new CLSID
                                oVB6Project.CompilerFilePath = CompilerFilePath
                                oVB6Project.BuildsDirectory = BuildsDirectory
                                If oVB6Project.Build() Then

                                    If oVB6Project.CLSID <> "" Then
                                        lComponents.Add(UCase(oVB6Project.NameFileBuild))
                                        lCLSID.Add(oVB6Project.CLSID & "#" & oVB6Project.MajorVersion & "." & oVB6Project.MinorVersion)
                                    End If

                                    If UCase(Path.GetExtension(oVB6Project.NameFileBuild)) = ".EXE" Then
                                        'For exe's files set compilation without compatibility and Save.
                                        oVB6Project.SetProjectProperty("CompatibleMode", Chr(34) & "0" & Chr(34), False)
                                    Else
                                        'Set compilation with compatibility and Save.
                                        oVB6Project.SetProjectProperty("CompatibleMode", Chr(34) & "2" & Chr(34), False)
                                    End If

                                    If VBPOutDirectory = "" Then
                                        oVB6Project.Save()
                                    Else
                                        oVB6Project.SaveAs(VBPOutDirectory)
                                        'If a new project file has been generated we must make the original project unchanged file.
                                        oVB6Project.SaveOriginal()
                                    End If

                                    If OutDir <> "" Then
                                        CopyFileTo(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild), OutDir)

                                        If WriteTime Then
                                            SetWriteLastTimeFile(Path.Combine(OutDir, oVB6Project.NameFileBuild))
                                        End If
                                    End If

                                Else

                                    If VBPOutDirectory = "" Then
                                        oVB6Project.Save()
                                    Else
                                        oVB6Project.SaveAs(VBPOutDirectory)
                                        'If a new project file has been generated we must make the original project unchanged file.
                                        oVB6Project.SaveOriginal()
                                    End If

                                    If Not ContinueOnError Then

                                        'Destroy object and exit
                                        oVB6Project.Dispose()
                                        Throw New Exception("> Error in compilation of the component '" & ProjectFilePath & "'")

                                    End If

                                End If

                            Else
                                'We get the component and its CLSID have already been compiled in the builds 
                                'directory.
                                '-----------------------------------------------------------------------------------
                                oComponent = New Component(Path.Combine(BuildsDirectory, oVB6Project.NameFileBuild))
                                If Not oComponent Is Nothing Then

                                    If oComponent.GetCLSID <> "" Then
                                        lComponents.Add(UCase(oVB6Project.NameFileBuild))
                                        lCLSID.Add(oComponent.GetCLSID & "#" & oComponent.GetMajorVersion & "." & oComponent.GetMinorVersion)
                                    End If

                                    oComponent.Dispose()
                                End If
                                '-----------------------------------------------------------------------------------
                            End If

                        End If

                        oVB6Project.Dispose()

                    End If

                End If

            Next
            '-------------------------------------------------------------------------------------

        End If

        'Clean .oca files
        CleanOCAFiles()


    End Sub

    Public Sub SetWriteLastTimeFile(ByVal sFile As String)

        Try

            'Dim bReadOnly As Boolean = False

            'If the file has the read-only attribute, we must remove it to be able to edit the
            'date and time and then return to set it.
            If (File.GetAttributes(sFile) And FileAttributes.ReadOnly) = FileAttributes.ReadOnly Then
                'bReadOnly = True
                File.SetAttributes(sFile, FileAttributes.Normal)
            End If

            'Edit date and time of the file
            File.SetLastWriteTime(sFile, _
                                  New Date(FormatDate(LastWriteDate, "Y"), _
                                           FormatDate(LastWriteDate, "M"), _
                                           FormatDate(LastWriteDate, "D"), _
                                           FormatTime(LastWriteTime, "H"), _
                                           FormatTime(LastWriteTime, "M"), _
                                           FormatTime(LastWriteTime, "S")))


            'If bReadOnly Then

            '   File.SetAttributes(sFile, FileAttributes.ReadOnly)

            'End If

            WriteLog(BuildsDirectory, "> The file '" & sFile & "' has been modified correctly.'", eTypeLog.Robot)

        Catch

            Throw New Exception("> The file '" & sFile & "' not has been modified.'")

        End Try
    End Sub

    Public Sub SetWriteLastTimeDir(ByVal sDirectory As String)

        Try

            For Each sFile As String In Directory.GetFiles(sDirectory)

                SetWriteLastTimeFile(sFile)

            Next

        Catch ex As Exception

            Throw New Exception(ex.Message)

        End Try

    End Sub

    Public Sub SetWriteLastTimeDirRecursive(ByVal sDirectory As String)

        Try

            SetWriteLastTimeDir(sDirectory)

            For Each sSubDirectory As String In Directory.GetDirectories(sDirectory)

                SetWriteLastTimeDirRecursive(sSubDirectory)

            Next

        Catch ex As Exception

            Throw New Exception(ex.Message)

        End Try

    End Sub

    Public Sub CleanBuildsDirectory()

        Try

            For Each sFile As String In Directory.GetFiles(BuildsDirectory)

                Try
                    Select Case UCase(Path.GetExtension(sFile))
                        Case ".DLL", ".OCX"
                            'Unregister component
                            Call Shell("regsvr32 /u /s " & sFile, AppWinStyle.NormalFocus, True)

                        Case ".EXE"
                            'Unregister exe - activex
                            Call Shell(sFile & " /unregserver", AppWinStyle.NormalFocus, True)

                    End Select
                Catch
                    WriteLog(BuildsDirectory, "> Failed to desregistration file '" & sFile & "'.", eTypeLog.Robot)
                End Try

                Try
                    File.Delete(sFile)
                    WriteLog(BuildsDirectory, "> File '" & sFile & "' deleted successfully.", eTypeLog.Robot)
                Catch
                    WriteLog(BuildsDirectory, "> Failed to delete file '" & sFile & "'.", eTypeLog.Robot)
                End Try

            Next

            If VBPOutDirectory <> "" And Directory.Exists(VBPOutDirectory) Then

                For Each sFile As String In Directory.GetFiles(VBPOutDirectory)

                    Try
                        File.Delete(sFile)
                        WriteLog(BuildsDirectory, "> File '" & sFile & "' deleted successfully.", eTypeLog.Robot)
                    Catch
                        WriteLog(BuildsDirectory, "> Failed to delete file '" & sFile & "'.", eTypeLog.Robot)
                    End Try

                Next

            End If

        Catch

            Throw New Exception("> Failed to clean the builds directory")

        End Try

    End Sub

    Public Sub CleanBuildsLogs()

        Try

            CleanLog(BuildsDirectory, eTypeLog.Builds)

            WriteLog(BuildsDirectory, "> The builds log has been cleaned successfully.", eTypeLog.Robot)

        Catch

            Throw New Exception("> Failed to clean the logs files.")

        End Try

    End Sub

    Public Sub CopyFileTo(ByVal sFile As String, ByVal sDirectoryCopy As String)

        Try
            If Not File.Exists(sFile) Then

                Throw New Exception("> The file where you want to copy the files is invalid or does not exist.")

            End If

            File.Copy(sFile, Path.Combine(sDirectoryCopy, Path.GetFileName(sFile)), True)

            WriteLog(BuildsDirectory, "> File '" & sFile & "' copied successfully.", eTypeLog.Robot)

        Catch

            Throw New Exception("> Failed to copy the file in the '" & sDirectoryCopy & "'.")

        End Try

    End Sub

    Public Sub CopyContentsBuildsDirTo(ByVal sDirectoryCopy As String)

        Try
            If Not Directory.Exists(sDirectoryCopy) Then

                Throw New Exception("> The directory where you want to copy the files is invalid or does not exist.")

            End If

            For Each sFile As String In Directory.GetFiles(BuildsDirectory)

                If UCase(Path.GetExtension(sFile)) <> ".OCA" Then

                    CopyFileTo(sFile, sDirectoryCopy)

                End If

            Next

        Catch

            Throw New Exception("> Failed to copy the builds directory files to '" & sDirectoryCopy & "'.")

        End Try


    End Sub

    Public Sub Copy(ByVal sSourceDir As String, ByVal sTargetDir As String)

        If Not Directory.Exists(sSourceDir) Then

            Throw New Exception("> The source directory is invalid or does not exist.")

        End If

        Try
            If Not Directory.Exists(sTargetDir) Then

                Directory.CreateDirectory(sTargetDir)

            End If

            For Each sDirectory As String In Directory.GetDirectories(sSourceDir)

                Copy(sDirectory, Path.Combine(sTargetDir, Path.GetFileName(sDirectory)))

            Next

            For Each sFile As String In Directory.GetFiles(sSourceDir)

                CopyFileTo(sFile, sTargetDir)

            Next

        Catch

            Throw New Exception("> Failed to copy subdirectories and files to '" & sTargetDir & "'.")

        End Try


    End Sub

    Public Sub SortReferences(ByVal sProject As String)

        If Not File.Exists(sProject) Then

            Throw New Exception("> The indicated project file is not valid or does not exist.")

        End If

        Dim oVB6Project As VB6Project = Nothing

        Try

            If File.Exists(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "ReferencesOrder.txt")) Then
                ReferencesOrder = GetAllLinesFileEncondingDefault(Path.Combine(Path.GetDirectoryName(GetExecutingAssembly.Location), "ReferencesOrder.txt"))
            End If

            If ReferencesOrder Is Nothing Then

                WriteLog(BuildsDirectory, "> The 'ReferencesOrder.txt' file does not exist or is empty.", eTypeLog.Robot)

            Else

                oVB6Project = New VB6Project(sProject)
                If oVB6Project.Load() Then

                    'Sort References and Save.
                    If oVB6Project.SortReferences(ReferencesOrder) Then
                        oVB6Project.Save()

                        WriteLog(BuildsDirectory, "> Project references sorting has been made successfully.", eTypeLog.Robot)

                    End If

                End If

            End If

        Catch

            Throw New Exception("> Failed to sort the project references.")

        Finally

            If Not oVB6Project Is Nothing Then oVB6Project.Dispose()

        End Try


    End Sub

    Public Sub Notify(ByVal sRecipients As String)

        If sRecipients = "" Then

            Throw New Exception("> You must indicate recipients to send mail.")

        End If

        Dim oEmail As EMail = Nothing

        Try

            oEmail = New EMail()

            oEmail.Recipients = sRecipients
            oEmail.MessageDescription = MessageDescription
            If ReadLog(BuildsDirectory, eTypeLog.Builds) = "" Then
                oEmail.MessageContentPlainText = MessageContentWithoutErrors
                oEmail.MessageContentHTMLText = "<font size=2 face=arial>" & MessageContentWithoutErrors & "</font>"
            Else
                oEmail.MessageContentPlainText = MessageContentWithErrors & _
                                                 vbCrLf & ReadLog(BuildsDirectory, eTypeLog.Builds)
                oEmail.MessageContentHTMLText = "<font size=2 face=arial>" & MessageContentWithErrors & _
                                                 "<br>" & Replace(ReadLog(BuildsDirectory, eTypeLog.Builds), vbCrLf, "<br>") & "</font>"
            End If

            oEmail.Send()

            WriteLog(BuildsDirectory, "> " & oEmail.errDescription, eTypeLog.Robot)

        Catch

            Throw New Exception("> Failed to notify the results of compilations.")

        Finally

            If Not oEmail Is Nothing Then oEmail.Dispose()

        End Try

    End Sub


#End Region

#Region "Private methods"

    Private Sub CleanOCAFiles()

        Try
            For Each sFile As String In Directory.GetFiles(BuildsDirectory)

                If UCase(Path.GetExtension(sFile)) = ".OCA" Then

                    File.Delete(sFile)

                End If

            Next
        Catch
        End Try

    End Sub

    Private Function FormatDate(ByVal StringDate As String, ByVal YMD As String) As Integer

        Dim PartsOfDate() As String

        Try
            PartsOfDate = Split(StringDate, "/")

            Select Case YMD
                Case "Y" 'Year
                    Return CType(PartsOfDate(2), Integer)
                Case "M" 'Month
                    Return CType(PartsOfDate(1), Integer)
                Case "D" 'Day
                    Return CType(PartsOfDate(0), Integer)
            End Select
        Catch
        End Try

        Return 0

    End Function

    Private Function FormatTime(ByVal StringTime As String, ByVal HMS As String) As Integer

        Dim PartsOfTime() As String

        Try
            PartsOfTime = Split(StringTime, ":")

            Select Case HMS
                Case "H" 'Hour
                    Return CType(PartsOfTime(0), Integer)
                Case "M" 'Minute
                    Return CType(PartsOfTime(1), Integer)
                Case "S" 'Second
                    Return CType(PartsOfTime(2), Integer)
            End Select
        Catch
        End Try

        Return 0

    End Function

    Private Function GetProjectFilePath(ByVal ProjectFileLine As String) As String
        Try
            Return Split(ProjectFileLine, "#")(0)
        Catch
        End Try

        Return ""

    End Function

    Private Function GetProjectProperties(ByVal ProjectFileLine As String) As String()

        Dim sProperties(0) As String

        Try

            Dim sLine() As String = Split(ProjectFileLine, "#")
            ReDim sProperties(sLine.Length - 2)

            For i As Integer = 1 To sLine.Length - 1
                sProperties(i - 1) = Replace(sLine(i), Chr(39), Chr(34)) 'Replace char ' by char ".
            Next

            Return sProperties

        Catch
        End Try

        Return sProperties

    End Function

#End Region

End Class
